use rs_orm::model::{
    field::{
        inner::{TableField, TableTrait},
        Field, FieldType, FkNo,
    },
    relation::ForeignKey,
    Meta, Model,
};
/// 机构

#[derive(Debug)]
#[allow(dead_code)]
struct Organization {
    id: Option<u32>,
    name: String,
}

impl Model for Organization {
    /// 表主键字段类型
    type PkType = u32;
    /// 表定义信息
    const META: Meta = Meta {
        table_name: "core_organization",
        field_list: &[
            Field {
                name: "id",
                table_field_name: "id",
                date_type: FieldType::Number,
                max_length: None,
                pk: true,
                auto_increment: true,
                remark: Some("机构编号"),
                fk_model_no: None,
                null: false,
            },
            Field {
                name: "name",
                table_field_name: "name",
                date_type: FieldType::Text,
                max_length: None,
                pk: false,
                auto_increment: false,
                remark: Some("机构名称"),
                fk_model_no: None,
                null: false,
            },
        ],
        index_list: None,
    };
    // 无外键1
    type FkModel1 = ();
    // 无外键2
    type FkModel2 = ();
    // 无外键3
    type FkModel3 = ();
    // 无外键4
    type FkModel4 = ();
    // 无外键5
    type FkModel5 = ();
    // 无外键6
    type FkModel6 = ();
    // 无外键7
    type FkModel7 = ();
    // 无外键8
    type FkModel8 = ();
    // 无外键9
    type FkModel9 = ();
    // 无外键10
    type FkModel10 = ();
}

// 新语法
#[derive(Debug)]
pub struct OrganizationModel {
    /// 机构编号
    pub id: TableField<u32>,
    /// 机构名称
    pub name: TableField<&'static str>,
}

impl TableTrait<OrganizationModel> for Organization {
    const COLUMN: OrganizationModel = OrganizationModel {
        id: TableField::new(0),
        name: TableField::new(1),
    };
}

/// 作者
//#[orm_meta(table_name = "core_user", table_pref = "core")]
#[derive(Debug)]
#[allow(dead_code)]
struct Author {
    //#[orm_field(name = "uid", pk = "true", db_type = "int unsign")]
    id: Option<u32>,
    //#[orm_field(db_type = "varchar", max_lenth = "60")]
    name: String,
    org: Option<ForeignKey<Organization>>,
}
impl Model for Author {
    /// 表主键字段类型
    type PkType = u32;
    /// 表定义信息
    const META: Meta = Meta {
        table_name: "core_author",
        field_list: &[
            Field {
                name: "id",
                table_field_name: "id",
                date_type: FieldType::Number,
                max_length: None,
                pk: true,
                auto_increment: true,
                remark: Some("作者编号"),
                fk_model_no: None,
                null: false,
            },
            Field {
                name: "name",
                table_field_name: "name",
                date_type: FieldType::Text,
                max_length: None,
                pk: false,
                auto_increment: false,
                remark: Some("作者姓名"),
                fk_model_no: None,
                null: false,
            },
            Field {
                name: "org",
                table_field_name: "org_id",
                date_type: FieldType::Number,
                max_length: None,
                pk: true,
                auto_increment: false,
                remark: Some("图书作者所属机构"),
                fk_model_no: Some(FkNo::One),
                null: true,
            },
        ],
        index_list: None,
    };
    // 无外键1
    type FkModel1 = Organization;
    // 无外键2
    type FkModel2 = ();
    // 无外键3
    type FkModel3 = ();
    // 无外键4
    type FkModel4 = ();
    // 无外键5
    type FkModel5 = ();
    // 无外键6
    type FkModel6 = ();
    // 无外键7
    type FkModel7 = ();
    // 无外键8
    type FkModel8 = ();
    // 无外键9
    type FkModel9 = ();
    // 无外键10
    type FkModel10 = ();
}

// 新语法
#[derive(Debug)]
pub struct AuthorModel {
    /// 作者编号
    pub id: TableField<u32>,
    /// 作者姓名
    pub name: TableField<&'static str>,
    /// 所属机构
    pub org_id: TableField<u32>,
}

impl TableTrait<AuthorModel> for Author {
    const COLUMN: AuthorModel = AuthorModel {
        id: TableField::new(0),
        name: TableField::new(1),
        org_id: TableField::new(2),
    };
}

/// 书籍
#[derive(Debug)]
#[allow(dead_code)]
struct Book {
    //#[orm_field(pk = true)]
    id: Option<u32>,
    //#[orm_field(db_type = "varchar", max_lenth = "60")]
    name: String,
    //#[orm_foreign(name = "author", null = "true", related_name = "book_authors")]
    author: Option<ForeignKey<Author>>,
}

impl Model for Book {
    /// 表主键字段类型
    type PkType = u32;
    /// 表定义信息
    const META: Meta = Meta {
        table_name: "core_book",
        field_list: &[
            Field {
                name: "id",
                table_field_name: "id",
                date_type: FieldType::Number,
                max_length: None,
                pk: true,
                auto_increment: true,
                remark: Some("图书编号"),
                fk_model_no: None,
                null: false,
            },
            Field {
                name: "name",
                table_field_name: "name",
                date_type: FieldType::Text,
                max_length: Some(30),
                pk: false,
                auto_increment: false,
                remark: Some("图书名称"),
                fk_model_no: None,
                null: false,
            },
            Field {
                name: "author",
                table_field_name: "author_id",
                date_type: FieldType::Number,
                max_length: None,
                pk: true,
                auto_increment: false,
                remark: Some("图书作者"),
                fk_model_no: Some(FkNo::One),
                null: true,
            },
        ],
        index_list: None,
    };
    // 外键1,为作者
    type FkModel1 = Author;
    // 无外键2
    type FkModel2 = ();
    // 无外键3
    type FkModel3 = ();
    // 无外键4
    type FkModel4 = ();
    // 无外键5
    type FkModel5 = ();
    // 无外键6
    type FkModel6 = ();
    // 无外键7
    type FkModel7 = ();
    // 无外键8
    type FkModel8 = ();
    // 无外键9
    type FkModel9 = ();
    // 无外键10
    type FkModel10 = ();
}

#[test]
fn test_query() {
    // let data = Organization::db_filter(
    //    Organization::TABLE.id.eq("rust") & Organization::TABLE.name.contains("hy"))
    //      .select(Organization::as_select())
    //      .exec(&db).await?;
    let query = Author::COLUMN.name.eq("hy")
        & Author::COLUMN
            .org_id
            .inner_join(Organization::COLUMN.id.eq(1));
    dbg!(&query);
    let filter = Author::db_filter(query).unwrap();
    // filter.extra_select(Author::TABLE.org_id.as_select())
    dbg!(filter);
}
#[test]
fn test_author_filter() {
    /*
    let expr_1 = QueryExpr::new_item("name", "rust");
    let expr_2 = QueryExpr::new_item("id", 3);
    let expr_3 = expr_1 & expr_2
        | (QueryExpr::new_item("author__name__startswith", "hy")
            & QueryExpr::new_item("author__id__gte", 10)
            & QueryExpr::new_item("author__org__name", "作协"));

    let _expr_4 = Organization::TABLE.id.eq("rust") & Organization::TABLE.name.contains("hy");

    let builder = Book::db_filter(expr_3).unwrap();


    //println!("{builder:#?}");
    let select_sql = builder.get_select_sql(true);
    println!("select sql :\n========\n{select_sql}");
    assert_eq!(builder.get_select_sql(false),"SELECT core_book.id,core_book.name,core_book.author_id FROM core_book \
        JOIN core_author AS author_core_author ON core_book.author_id = author_core_author.id \
        JOIN core_organization AS author_org_core_organization ON author_core_author.org_id = author_org_core_organization.id \
        WHERE  \
        ( core_book.name = 'rust' AND core_book.id = 3 ) OR \
        ( ( author_core_author.name LIKE 'hy%' AND author_core_author.id >= 10 ) \
        AND author_org_core_organization.name = '作协' )");
     */
    // Author::filter((Q("name__like", "hy") & Q("id__gte", 1)) & !Q("id__gte", 1));
    /*
    let authors: Vec<Author> = build!(Book, name__contains = "test", id__gte = 1)
        .filter(Q("author__name__contains","hy"))
        .select("id", "name","author__name")
        .limit(10)
        .exec(&conn)?;
     */
}
